//
//  HJFlutterManager.m
//  KaiChat
//
//  Created by lx on 2024/3/21.
//

#import "HJFlutterManager.h"
#import "AppDelegate.h"
#import "HJNavigationController.h"
#import "HJAddFriendController.h"
#import "HJFlutterMethod.h"
#import "HJMinePresent.h"
#import "HJUserInfoController.h"
#import "HJShareController.h"
#import "HJPersonalCenterV2Controller.h"
#import "HJDAppController.h"
#import "HJFlutterController.h"
#import "HJInformationPresent.h"
#import "HJVideoPlayController.h"
#import "HJPhotoBrowser.h"

@interface HJFlutterManager()

#if LOADFLUTTER
@property (nonatomic, strong) FlutterEngine *mainEngine;
@property (nonatomic, strong) NSMutableDictionary *engines;
@property (nonatomic, copy, nullable) NSString *storeReference;
@property (nonatomic, copy) void (^getWalletInfoComplete)(NSDictionary *walletInfo);
#endif

@end



@implementation HJFlutterManager


static HJFlutterManager *instance;

+ (nonnull instancetype)sharedManager {
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        instance = [self new];
        //        NSLog(@"%@", OPENFLUTTER);
        [[NSNotificationCenter defaultCenter] addObserver:instance selector:@selector(handleOpenKaiPayNotification) name:openKaiPayNotification object:nil];
    });
    return instance;
}


- (NSString *)channelName {
    return @"com.kai.bitchat.bridge";
}

- (NSString *)mainEngineName {
    return @"main";
}

#if LOADFLUTTER
- (NSMutableDictionary *)engines {
    if (!_engines) {
        _engines = [NSMutableDictionary dictionary];
    }
    return _engines;
}

- (FlutterEngine *)mainEngine {
    if (!_mainEngine) {
        _mainEngine = [self engineWithName:self.mainEngineName];
        FlutterMethodChannel *walletChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:_mainEngine.binaryMessenger];
        TJWeakify(self)
        [walletChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
            [weakself methodCallHandler:call result:result];
        }];
    }
    return _mainEngine;
}

- (FlutterEngine *)engineWithName:(NSString *)name {
    if (self.engines.count == 0) {
        _storeReference = nil;
    }
    FlutterEngine *flutterEngine = [self.engines objectForKey:name];
    if (!flutterEngine) {
        flutterEngine = [[FlutterEngine alloc] initWithName:name];
        if (flutterEngine) {
            [self.engines setObject:flutterEngine forKey:name];
            NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[self getFlutterMessageWithPage:HJFlutterPageWallet arguments:@{}], nil];
            if (!isEmptyString(_storeReference)) {
                NSLog(@"引用_storeReference:%@",_storeReference);
                [args addObject:_storeReference];
            }
            NSLog(@"创建引擎成功 %@", name);
            [flutterEngine runWithEntrypoint:name libraryURI:NULL initialRoute:NULL entrypointArgs:args];
            [GeneratedPluginRegistrant registerWithRegistry:flutterEngine];
        }
    }
    return flutterEngine;
}
#endif

static char * toCString(NSString *string) {
    return (char *)string.UTF8String;
}

static NSString *CToString(char *value) {
    return [NSString stringWithCString:value encoding:NSUTF8StringEncoding];
}

- (void)handleOpenKaiPayNotification {
    if (_mainEngineController) {
        [_mainEngineController openPageWithName:HJFlutterPageDApp];
    } else {
        HJFlutterController *flutterController = [[HJFlutterController alloc] initWithName:HJFlutterPageDApp];
        [[HJTools currentNavController] pushViewController:flutterController];
    }
#if LOADFLUTTER
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
        FlutterMethodChannel *mainChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:HJFlutterManager.sharedManager.mainEngine.binaryMessenger];
        [mainChannel invokeMethod:@"goBrowser" arguments:@{@"url": getKaiPayUrl()}.mj_JSONString result:^(id  _Nullable result) {}];
    });
#endif
    
}

#if LOADFLUTTER
//flutter -> iOS通信的入口
- (void)methodCallHandler:(FlutterMethodCall* )call result:(FlutterResult)result {
    
    NSLog(@"methodCallHandler.method = %@, call.arguments = %@", call.method, call.arguments);
    
    
    if ([call.method isEqual:HJFlutterMethod.setBaseInfo]) {
        result([self getFlutterMessage].mj_JSONString);
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.getPublicAddress]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        //        NSString *MPCWalletAddress = arguments[@"address"];
        NSLog(@"address-----%@",arguments);
        //        HJUserInfo.MPCWalletAddress = MPCWalletAddress;
        if (self.getWalletInfoComplete) {
            self.getWalletInfoComplete(arguments);
        }
        _getWalletInfoComplete = nil;
        result(@"ok");
        
        dispatch_async_sql_queue(^{
            HJUserModel *userModel = [HJUserModel currentAccountModel];
            userModel.walletInfo = arguments;
            [userModel bg_saveOrUpdate];
        });
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.googleAuth]) {
        [HJMinePresent loadUserInfoComplete:^(HJUserModel * _Nullable userModel) {
            [self setBaseInfo];
        }];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.appleAuth]) {
        [HJMinePresent loadUserInfoComplete:^(HJUserModel * _Nullable userModel) {
            [self setBaseInfo];
        }];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.tabShowOrHidden]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        if (!arguments) return;
        getMainController().tabBar.hidden = [arguments[@"tab_state"] boolValue];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.sendStoreReference]) {
        NSLog(@"收到了引用_storeReference:%@",call.arguments);
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        if (!arguments) return;
        _storeReference = arguments[@"reference"];
        NSLog(@"设置了引用_storeReference:%@",_storeReference);
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.tokenExpire]) {
        [HJNetworking.shareNetwork tokenError];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.openNativePage]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        long action = [arguments[@"action"] longValue];
        NSString *path = arguments[@"path"];
        
        //这里还需要匹配path打开指定的VC
        if (action == 0) {
            if ([path isEqualToString:@"/pages/activity/activityList"]) {
                //IM模块中的活动列表
                //todo
            } else if ([path isEqualToString:@"/pages/chat/addContact"]) {
                //IM模块中的添加好友
                if (isProduction()) {
                    HJUserInfoController *infoController = [[HJUserInfoController alloc] init];
                    infoController.Uid = @"Kai00001";
                    [[HJTools currentNavController] pushViewController:infoController];
                } else {
                    HJNavigationController *navController = [[HJNavigationController alloc] initWithRootViewController:[[HJAddFriendController alloc] init]];
                    [[HJTools currentViewController] presentViewController:navController animated:YES completion:nil];
                }
                return;
            }
        } else if (action == 1) {
            NSURL *targetURL = [NSURL URLWithString:path];
            if ([[UIApplication sharedApplication] canOpenURL:targetURL]) {
                [[UIApplication sharedApplication] openURL:targetURL options:@{} completionHandler:nil];
            }
        } else {
            return;
        }
    }
    
    if ([call.method isEqual:HJFlutterMethod.closeFlutterPage]) {
        if ([NSStringFromClass(self.containController.class) isEqualToString:@"HJFlutteAlertController"]) {
            UIViewController *containController = self.containController;
            self.containController = nil;
            [containController dismissViewControllerAnimated:NO completion:nil];
            return;
        }
        [HJTools.currentNavController popViewControllerAnimated:YES];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.h5CallNative]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        NSString *method = arguments[@"method"];
        NSString *params = arguments[@"params"];
        if ([method isEqualToString:@"linkJoinGroup"]) {
            [(AppDelegate *)UIApplication.sharedApplication.delegate openURL:params.URL];
        }
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.integralTask]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        [self startIntegralTask:arguments];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.previewMedia]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        NSArray *datas = arguments[@"datas"];
        NSString *type = arguments[@"type"];
        NSInteger index = [arguments[@"index"] integerValue];
        NSLog(@"datas = %@", datas);

        if ([type isEqualToString:@"video"]) {
            HJVideoPlayController *videoPlayController = [[HJVideoPlayController alloc] init];
            videoPlayController.url = datas.firstObject;
            [[HJTools currentViewController] presentViewController:videoPlayController animated:YES completion:nil];
            return;
        }
        
        NSMutableArray *Marr = [NSMutableArray array];
        [datas enumerateObjectsUsingBlock:^(NSString *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            HJPhotoItem *item = [[HJPhotoItem alloc] init];
            item.thumbUrl = obj;
            item.originalUrl = obj;
            [Marr addObject:item];
        }];
        HJPhotoBrowser *browser = [HJPhotoBrowser browserWithPhotoItems:Marr selectedIndex:index];
        [browser showFromViewController:[HJTools currentViewController]];
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.operateSuccess]) {
        NSDictionary *arguments = [call.arguments mj_JSONObject];
        if (!arguments) return;
        NSString *action = arguments[@"action"];
        if ([action isEqualToString:@"comment"] || [action isEqualToString:@"like"] || [action isEqualToString:@"views"]) {
            [[NSNotificationCenter defaultCenter] postNotificationName:flutterPageOperateNotification object:arguments];
            result(@"1");
            return;
        }
        
        if ([action isEqualToString:@"share"] || [action isEqualToString:@"forward"]) {
            NSString *type = arguments[@"type"];
            NSString *informationId = arguments[@"id"];
            HJShareController *shareController = [[HJShareController alloc] init];
            shareController.objects = @[[NSString stringWithFormat:@"%@?articleType=%@&userId=%@&articleId=%@",getNewsShareUrl(), type,  HJUserInfo.userId, informationId]];
            [shareController setSucceedBlock:^{
                [HJInformationPresent statisticsUserShareDataWithType:[type intValue] newsId:informationId complete:^(NSError * _Nullable error) {
                    if (!error) {
                        [[NSNotificationCenter defaultCenter] postNotificationName:flutterPageOperateNotification object:arguments];
                    }
                }];
                result(@"1");
            }];
            [HJTools.currentViewController presentViewController:shareController animated:YES completion:nil];
            return;
        }
        
        result(@"ok");
        return;
    }
    
    if ([call.method isEqual:HJFlutterMethod.sharePoster]) {
        
        FlutterStandardTypedData *bytesList = call.arguments;
        NSData *imageData = bytesList.data;
        
        NSString *imagePath = @"myImage.png".tj_documentsPath;
        BOOL success = [imageData writeToFile:imagePath atomically:YES];
        
        if (success) {
            TJWeakify(self)
            HJShareController *shareController = [[HJShareController alloc] init];
            [shareController setPopBlock:^{
                [weakself refreshIntegralController];
            }];
            NSURL *imageURL = [NSURL fileURLWithPath:imagePath];
            shareController.objects = @[imageURL];
            [HJTools.currentViewController presentViewController:shareController animated:YES completion:nil];
        } else {
            NSLog(@"图片保存失败");
        }
        result(@"ok");
        return;
    }
    
}
#endif

- (void)startIntegralTask:(NSDictionary *)dict {
    
    HJIntegralTaskType type = [dict[@"taskCode"] integerValue];
    NSString *uid = dict[@"uid"];
    
    if (type == HJIntegralTaskTypeNickname || type == HJIntegralTaskTypeAvatar) {
        
        HJPersonalCenterV2Controller *vc = [[HJPersonalCenterV2Controller alloc]init];
        TJWeakify(self)
        vc.popBlock = ^{
            [weakself refreshIntegralController];
        };
        [[HJTools currentNavController] pushViewController:vc];
        return;
    }
    
    if (type == HJIntegralTaskTypeAddFridend) {
        TJWeakify(self)
        if (isEmptyString(dict[@"uid"])) {
            HJAddFriendController *addFriendController = [[HJAddFriendController alloc] init];
            [addFriendController setPopBlock:^{
                [weakself refreshIntegralController];
            }];
            HJNavigationController *navController = [[HJNavigationController alloc] initWithRootViewController:addFriendController];
            [[HJTools currentViewController] presentViewController:navController animated:YES completion:nil];
        } else {
            HJUserInfoController *infoController = [[HJUserInfoController alloc] init];
            infoController.userId = toString(dict[@"uid"]);
            [infoController setPopBlock:^{
                [weakself refreshIntegralController];
            }];
            [[HJTools currentNavController] pushViewController:infoController];
        }
        return;
    }
    
    //加入群聊（官方群，群ID：83）
    if (type == HJIntegralTaskTypeJoinGroup) {
        [(AppDelegate *)UIApplication.sharedApplication.delegate openURL:@"kai://?groupId=83".URL popBlock:^{
            [self refreshIntegralController];
        }];
        return;
    }
 
    if (type == HJIntegralTaskTypeSingeChat || type == HJIntegralTaskTypeGroupChat || type == HJIntegralTaskTypeKaiPayTransfer) {
        [[HJTools currentNavController] popToRootViewControllerAnimated:NO];
        if (getMainController().selectedIndex != 0) {
            [getMainController() tj_setSelectedIndex:0];
        }
        return;
    }
    
}

- (void)getWalletInfoComplete:(void (^)(NSDictionary *walletInfo))complete {
#if LOADFLUTTER
    _getWalletInfoComplete = complete;
    
    FlutterMethodChannel *mainChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:HJFlutterManager.sharedManager.mainEngine.binaryMessenger];
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setValue:HJUserInfo.userId forKey:@"userId"];
    [mainChannel invokeMethod:HJFlutterMethod.getPublicAddress arguments:dict.mj_JSONString result:^(id  _Nullable result) {}];
#endif
    
}

- (void)refreshIntegralController {
#if LOADFLUTTER
    NSLog(@"refreshIntegralController");
    FlutterMethodChannel *walletChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:HJFlutterManager.sharedManager.mainEngine.binaryMessenger];
    [walletChannel invokeMethod:HJFlutterMethod.setBaseInfo arguments:[self getFlutterMessageWithPage:HJFlutterPageIntegral arguments:@{}] result:^(id  _Nullable result) {
        NSLog(@"result = %@", result);
    }];
#endif
}

- (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments result:(void (^__nullable)(id _Nullable result))result {
#if LOADFLUTTER
    FlutterMethodChannel *walletChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:HJFlutterManager.sharedManager.mainEngine.binaryMessenger];
    [walletChannel invokeMethod:method arguments:arguments result:result];
#endif
}

- (void)setBaseInfo {
    
#if LOADFLUTTER
    FlutterMethodChannel *walletChannel = [FlutterMethodChannel methodChannelWithName:self.channelName binaryMessenger:HJFlutterManager.sharedManager.mainEngine.binaryMessenger];
    [walletChannel invokeMethod:HJFlutterMethod.setBaseInfo arguments:[self getFlutterMessage].mj_JSONString result:^(id  _Nullable result) {
        NSLog(@"result = %@", result);
    }];
#endif
    
}

- (void)removeEnginetForKey:(NSString *)key {
#if LOADFLUTTER
    FlutterEngine *eng = [self.engines objectForKey:key];
    [eng destroyContext];
    eng = nil;
    [self.engines removeObjectForKey:key];
#endif
}

- (void)preloadWalletEngine {
#if LOADFLUTTER
    dispatch_async_main_queue(^{
        [self engineWithName:self.mainEngineName];
    });
#endif
}

- (void)destroyAllEngine {
#if LOADFLUTTER
    [self.engines enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        [obj destroyContext];
    }];
    [self.engines removeAllObjects];
    _mainEngineController = nil;
    _storeReference = nil;
    self -> _mainEngine = nil;
#endif
    
}

- (NSDictionary *)getFlutterMessage {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setValue:HJUserInfo.token forKey:@"token"];
    [dict setValue:HJUserInfo.avatar forKey:@"iconUrl"];
    [dict setValue:[NSString stringWithFormat:@"%@/", getBaseUrlString()] forKey:@"base_url"];
    [dict setValue:getAppChannel() forKey:@"channel"];
    [dict setValue:getAppVersion() forKey:@"version_no"];
    [dict setValue:@1 forKey:@"device_type"];
    [dict setValue:HJUserInfo.email forKey:@"email"];
    [dict setValue:@101 forKey:@"app_id"];
    [dict setValue:HJUserInfo.userId forKey:@"userId"];
    [dict setValue:HJUserInfo.model.googleEmail forKey:@"google_email"];
    [dict setValue:HJUserInfo.model.appleUserId forKey:@"apple_user_id"];
    [dict setValue:@(isHiddenAppleServe()) forKey:@"isAppleEnterprise"];
    [dict setValue:@(getAppEnvType()) forKey:@"appEnvType"];
    [dict setValue:@(isUseCrypto()) forKey:@"isUseCrypto"];
    [dict setValue:@(HJUserInfo.enableGray) forKey:@"enable_gray"];
    return dict;
}

- (NSString *)getFlutterMessageWithPage:(NSString *)page arguments:(id)arguments {
    if (!arguments) {
        arguments = @{};
    }
    return @{@"page": page,@"userMsg": [self getFlutterMessage], @"parameter": [arguments mj_JSONString]}.mj_JSONString;
}


@end
